home *** CD-ROM | disk | FTP | other *** search
/ Tech Win 1999 February / TECH Win 02-1999 Disc A.iso / ols / lzh / tcl211.lzh / DLLSRC.lzh / startmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-27  |  10.7 KB  |  404 lines

  1. /*-------------------------------------------
  2.  STARTMENU.C
  3.   スタートメニューの改造
  4.   KAZUBON 1997-1998
  5. ---------------------------------------------*/
  6.  
  7. #include "tcdll.h"
  8.  
  9. static void OnDrawItem(HWND hwnd, DRAWITEMSTRUCT* pdis);
  10. static BOOL IsStartMenu(HMENU hmenu);
  11. void DeleteStartMenuRes(void);
  12.  
  13. /*------------------------------------------------
  14.  Globals
  15. --------------------------------------------------*/
  16. BOOL bStartMenu = FALSE;
  17. HWND hwndBar = NULL;           // タスクバーのウィンドウハンドル
  18. WNDPROC oldWndProcBar = NULL;  // ウィンドウプロシージャを保存
  19. HDC hdcMemMenu = NULL;         // メニュー描画用メモリDC
  20. HBITMAP hbmpMenu = NULL;       // メニュー描画用ビットマップ
  21. HDC hdcMemMenuLeft = NULL;     // 「Windows95」部分用メモリDC
  22. HBITMAP hbmpMenuLeft = NULL;   // 「Windows95」部分用ビットマップ
  23. int hStartMenu = 0;            // メニューの高さを保存
  24. COLORREF colMenuLeft;          // 色
  25. static BOOL bTile = FALSE;     // 並べる
  26.  
  27. /*------------------------------------------------
  28.  タスクバーのサブクラスプロシージャ
  29. --------------------------------------------------*/
  30. LRESULT CALLBACK WndProcBar(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  31. {
  32.     switch(message)
  33.     {
  34.         // メニューのオーナードロー
  35.         case WM_DRAWITEM:
  36.         {
  37.             DRAWITEMSTRUCT* pdis;
  38.             
  39.             if(!bStartMenu) break;
  40.             pdis = (DRAWITEMSTRUCT*)lParam;
  41.             // スタートメニューでなかったらそのまま
  42.             if(wParam || !IsStartMenu((HMENU)pdis->hwndItem)) break;
  43.             OnDrawItem(hwnd, pdis);
  44.             return 1;
  45.         }
  46.         // システム色変更
  47.         case WM_SYSCOLORCHANGE:
  48.             if(hdcMemMenu) DeleteDC(hdcMemMenu); hdcMemMenu = NULL;
  49.             if(hbmpMenu) DeleteObject(hbmpMenu); hbmpMenu = NULL;
  50.             break;
  51.         // v1.7  タスクバーの表示が乱れるのを防ぐ
  52.         case WM_EXITSIZEMOVE:
  53.             PostMessage(hwnd, WM_SIZE, SIZE_RESTORED, 0);
  54.             break;
  55.         
  56.         case WM_DESTROY:
  57.             DeleteStartMenuRes();
  58.             break;
  59.     }
  60.     return CallWindowProc(oldWndProcBar, hwnd, message, wParam, lParam);
  61. }
  62.  
  63. /*------------------------------------------------
  64.  メニューのオーナードロー
  65. --------------------------------------------------*/
  66. void OnDrawItem(HWND hwnd, DRAWITEMSTRUCT* pdis)
  67. {
  68.     HDC hdc;
  69.     RECT rcBox, rcItem;
  70.     HBRUSH hbr;
  71.     BITMAP bmp;
  72.  
  73.     hdc = pdis->hDC;
  74.     CopyRect(&rcItem, &(pdis->rcItem));
  75.     GetClipBox(hdc, &rcBox); // メニュー全体の大きさ
  76.  
  77.     // 描画用メモリDCとビットマップの作成
  78.     if(hdcMemMenu == NULL ||
  79.         (hStartMenu != rcBox.bottom && rcBox.left == 0))
  80.     {
  81.         if(hdcMemMenu) DeleteDC(hdcMemMenu);
  82.         if(hbmpMenu) DeleteObject(hbmpMenu);
  83.                 
  84.         hdcMemMenu = CreateCompatibleDC(hdc);
  85.         hbmpMenu = CreateCompatibleBitmap(hdc, rcBox.right, rcBox.bottom);
  86.         SelectObject(hdcMemMenu, hbmpMenu);
  87.         hbr = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  88.         FillRect(hdcMemMenu, &rcBox, hbr);
  89.         hStartMenu = rcBox.bottom;
  90.     }
  91.     
  92.     SelectObject(hdcMemMenu, (HFONT)GetCurrentObject(hdc, OBJ_FONT));
  93.     
  94.     // 背景色、文字色の設定
  95.     if(pdis->itemState & ODS_FOCUS)
  96.     {
  97.         SetTextColor(hdcMemMenu, GetSysColor(COLOR_HIGHLIGHTTEXT));
  98.         SetBkColor(hdcMemMenu, GetSysColor(COLOR_HIGHLIGHT));
  99.     }
  100.     else
  101.     {
  102.         SetTextColor(hdcMemMenu, GetSysColor(COLOR_MENUTEXT));
  103.         SetBkColor(hdcMemMenu, GetSysColor(COLOR_MENU));
  104.     }
  105.     
  106.     // メモリDCにデフォルトの描画をさせる
  107.     pdis->hDC = hdcMemMenu;
  108.     CallWindowProc(oldWndProcBar, hwnd, WM_DRAWITEM, 0, (LPARAM)pdis);
  109.     
  110.     // 「Windows95」の幅が、pdis->rcItem.leftに入ってくる
  111.     rcItem.right = pdis->rcItem.left;
  112.     
  113.     if(rcItem.right > 0)
  114.     {
  115.         COLORREF col;
  116.         
  117.         if(!bTile)
  118.         {
  119.             //「色」で塗りつぶし
  120.             col = colMenuLeft;
  121.             if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  122.             hbr = CreateSolidBrush(col);
  123.             FillRect(hdcMemMenu, &rcItem, hbr);
  124.             DeleteObject(hbr);
  125.         }
  126.         
  127.         if(hbmpMenuLeft)
  128.             GetObject(hbmpMenuLeft, sizeof(BITMAP), &bmp);
  129.         
  130.         if(hbmpMenuLeft) 
  131.         // && rcItem.bottom > rcBox.bottom - bmp.bmHeight)
  132.         {
  133.             int i, j;
  134.             // ビットマップ描画
  135.             for(i = 0; ; i++)
  136.             {
  137.                 int y, ysrc, h, x, w;
  138.                 for(j = 0; ; j++)
  139.                 {
  140.                     y = rcBox.bottom - ((i + 1) * bmp.bmHeight);
  141.                     ysrc = 0;
  142.                     h = bmp.bmHeight;
  143.                     if(y < 0)
  144.                     {
  145.                         y = 0;
  146.                         ysrc = ((i + 1) * bmp.bmHeight) - rcBox.bottom;
  147.                         h -= ysrc;
  148.                     }
  149.                     x = j * bmp.bmWidth; w = bmp.bmWidth;
  150.                     if(x + w > rcItem.right)
  151.                     {
  152.                         w -= ((j + 1) * bmp.bmWidth) - rcItem.right;
  153.                     }
  154.                     if(w > 0 && h > 0)
  155.                         BitBlt(hdcMemMenu, x, y, w, h,
  156.                             hdcMemMenuLeft, 0, ysrc, SRCCOPY);
  157.                     if(!bTile || w < bmp.bmWidth) break;
  158.                 }
  159.                 if(!bTile || y == 0) break;
  160.             }
  161.         }
  162.     }
  163.  
  164.     // 本当のDCにまとめて描画
  165.     BitBlt(hdc, 0, rcItem.top,
  166.         pdis->rcItem.right, rcItem.bottom - rcItem.top,
  167.         hdcMemMenu, 0, rcItem.top, SRCCOPY);
  168.     pdis->hDC = hdc;
  169. }
  170.  
  171. /*--------------------------------------------------
  172.  スタートメニュー改造の初期化
  173. ----------------------------------------------------*/
  174. void SetStartMenu(HWND hwndClock)
  175. {
  176.     char fname[1024];
  177.  
  178.     EndStartMenu();
  179.     
  180.     // タスクバーのサブクラス化(v1.7より必ずサブクラス化)
  181.     hwndBar = GetParent(GetParent(hwndClock)); // Shell_TrayWnd
  182.     oldWndProcBar = (WNDPROC)GetWindowLong(hwndBar, GWL_WNDPROC);
  183.     SetWindowLong(hwndBar, GWL_WNDPROC, (LONG)WndProcBar);
  184.     
  185.     bStartMenu = GetMyRegLong(NULL, "StartMenu", FALSE);
  186.     
  187.     if(!bStartMenu) return;
  188.     
  189.     colMenuLeft = GetMyRegLong(NULL, "StartMenuCol",
  190.         RGB(128, 128, 128));
  191.     
  192.     bTile = GetMyRegLong(NULL, "StartMenuTile", FALSE);
  193.     
  194.     GetMyRegStr(NULL, "StartMenuBmp", fname, "");
  195.     
  196.     if(fname[0]) // 「Windows95」部分用のメモリDCとビットマップ作成
  197.     {
  198.         hbmpMenuLeft = ReadBitmap(hwndBar, fname, FALSE);
  199.         if(hbmpMenuLeft)
  200.         {
  201.             HDC hdc;
  202.             hdc = GetDC(hwndBar);
  203.             hdcMemMenuLeft = CreateCompatibleDC(hdc);
  204.             SelectObject(hdcMemMenuLeft, hbmpMenuLeft);
  205.             ReleaseDC(hwndBar, hdc);
  206.         }
  207.     }
  208. }
  209.  
  210. /*--------------------------------------------------
  211.  元に戻す
  212. ----------------------------------------------------*/
  213. void DeleteStartMenuRes(void)
  214. {
  215.     if(hdcMemMenu) DeleteDC(hdcMemMenu); hdcMemMenu = NULL;
  216.     if(hbmpMenu) DeleteObject(hbmpMenu); hbmpMenu = NULL;
  217.     if(hdcMemMenuLeft) DeleteDC(hdcMemMenuLeft); hdcMemMenuLeft = NULL;
  218.     if(hbmpMenuLeft) DeleteObject(hbmpMenuLeft); hbmpMenuLeft = NULL;
  219. }
  220. void EndStartMenu(void)
  221. {
  222.     if(hwndBar && IsWindow(hwndBar) && oldWndProcBar)
  223.         SetWindowLong(hwndBar, GWL_WNDPROC, (LONG)oldWndProcBar);
  224.     hwndBar = NULL; oldWndProcBar = NULL;
  225.     
  226.     DeleteStartMenuRes();
  227. }
  228.  
  229. /*--------------------------------------------------
  230.  スタートメニューかどうか判別
  231. ----------------------------------------------------*/
  232. BOOL IsStartMenu(HMENU hmenu)
  233. {
  234.     int i, count, id;
  235.     
  236.     count = GetMenuItemCount(hmenu);
  237.     for(i = 0; i < count; i++)
  238.     {
  239.         id = GetMenuItemID(hmenu, i);
  240.         // 「ヘルプ」があればスタートメニュー
  241.         if(id == 503) return TRUE;
  242.     }
  243.     return FALSE;
  244. }
  245.  
  246. // ------------------------------------------------------
  247. // 以下、IE4用
  248.  
  249. LRESULT CALLBACK WndProcStartMenu(HWND hwnd, UINT message,
  250.     WPARAM wParam, LPARAM lParam);
  251. HWND hwndStartMenu = NULL; // スタートメニューのウィンドウハンドル
  252. WNDPROC oldWndProcStartMenu = NULL;
  253. void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint);
  254.  
  255. /*--------------------------------------------------
  256.  スタートメニューウィンドウのサブクラス化
  257. ----------------------------------------------------*/
  258. void InitStartMenuIE4(void)
  259. {
  260.     HWND hwnd, hwndChild;
  261.     char classname[80];
  262.     RECT rc1, rc2;
  263.     
  264.     SetMyRegLong("StartMenu", "count", 0);
  265.     
  266.     // スタートメニューを探す
  267.     hwnd = GetDesktopWindow();
  268.     hwnd = GetWindow(hwnd, GW_CHILD);
  269.     while(hwnd)
  270.     {
  271.         GetClassName(hwnd, classname, 80);
  272.         if(lstrcmpi(classname, "BaseBar") == 0)
  273.         {
  274.             if(GetWindowThreadProcessId(hwnd, NULL) ==
  275.                 GetCurrentThreadId())
  276.             {
  277.                 hwndChild = GetWindow(hwnd, GW_CHILD);
  278.                 GetClientRect(hwnd, &rc1);
  279.                 GetClientRect(hwndChild, &rc2);
  280.                 if(rc1.right - rc2.right == 21 || rc2.right == 0)
  281.                 {
  282.                     break;
  283.                 }
  284.             }
  285.         }
  286.         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  287.     }
  288.     if(hwnd == NULL) return;
  289.     
  290.     // サブクラス化
  291.     oldWndProcStartMenu = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);
  292.     SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProcStartMenu);
  293.     hwndStartMenu = hwnd;
  294. }
  295.  
  296. /*--------------------------------------------------
  297.  スタートメニューウィンドウを元に戻す
  298. ----------------------------------------------------*/
  299. void ClearStartMenuIE4(void)
  300. {
  301.     if(hwndStartMenu && IsWindow(hwndStartMenu) && oldWndProcStartMenu)
  302.         SetWindowLong(hwndStartMenu, GWL_WNDPROC, (LONG)oldWndProcStartMenu);
  303.     hwndStartMenu = NULL; oldWndProcStartMenu = NULL;
  304. }
  305.  
  306. /*------------------------------------------------
  307.  スタートメニューのサブクラスプロシージャ
  308. --------------------------------------------------*/
  309. LRESULT CALLBACK WndProcStartMenu(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  310. {
  311.     switch(message)
  312.     {
  313.         // メニューの描画
  314.         case WM_PAINT:
  315.         {
  316.             PAINTSTRUCT ps;
  317.             HDC hdc;
  318.             if(!bStartMenu) break;
  319.             hdc = BeginPaint(hwnd, &ps);
  320.             OnPaintStartmenuIE4(hwnd, hdc, FALSE);
  321.             EndPaint(hwnd, &ps);
  322.             return 0;
  323.         }
  324.         case WM_PRINT:
  325.         {
  326.             LRESULT r;
  327.             if(!bStartMenu) break;
  328.             r = CallWindowProc(oldWndProcStartMenu, hwnd, message, wParam, lParam);
  329.             OnPaintStartmenuIE4(hwnd, (HDC)wParam, TRUE);
  330.             return r;
  331.         }
  332.         // システム色変更
  333.         case WM_SYSCOLORCHANGE:
  334.             break;
  335.     }
  336.     return CallWindowProc(oldWndProcStartMenu, hwnd, message, wParam, lParam);
  337. }
  338.  
  339. /*------------------------------------------------
  340.  スタートメニューの描画
  341. --------------------------------------------------*/
  342. void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint)
  343. {
  344.     RECT rc, rcWin;
  345.     COLORREF col;
  346.     HBRUSH hbr;
  347.     BITMAP bmp;
  348.     int hClient, wClient;
  349.     
  350.     GetClientRect(hwnd, &rc);
  351.     rc.right = 21;
  352.     wClient = rc.right; hClient = rc.bottom;
  353.     if(bPrint)
  354.     {
  355.         POINT pt;
  356.         int dx, dy;
  357.         GetWindowRect(hwnd, &rcWin);
  358.         pt.x = 0; pt.y = 0;
  359.         ClientToScreen(hwnd, &pt);
  360.         dx = pt.x - rcWin.left; dy = pt.y - rcWin.top;
  361.         rc.left += dx; rc.right += dx;
  362.         rc.top += dy; rc.bottom += dy;
  363.     }
  364.     //「色」で塗りつぶし
  365.     col = colMenuLeft;
  366.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  367.     hbr = CreateSolidBrush(col);
  368.     FillRect(hdc, &rc, hbr);
  369.     DeleteObject(hbr);
  370.     if(hbmpMenuLeft)
  371.     {
  372.         int i, j;
  373.         GetObject(hbmpMenuLeft, sizeof(BITMAP), &bmp);
  374.         // ビットマップ描画
  375.         for(i = 0; ; i++)
  376.         {
  377.             int y, ysrc, h, x, w;
  378.             for(j = 0; ; j++)
  379.             {
  380.                 y = hClient - ((i + 1) * bmp.bmHeight);
  381.                 ysrc = 0;
  382.                 h = bmp.bmHeight;
  383.                 if(y < 0)
  384.                 {
  385.                     y = 0;
  386.                     ysrc = ((i + 1) * bmp.bmHeight) - hClient;
  387.                     h -= ysrc;
  388.                 }
  389.                 x = j * bmp.bmWidth; w = bmp.bmWidth;
  390.                 if(x + w > wClient)
  391.                 {
  392.                     w -= ((j + 1) * bmp.bmWidth) - wClient;
  393.                 }
  394.                 if(w > 0 && h > 0)
  395.                     BitBlt(hdc, rc.left + x, rc.top + y, w, h,
  396.                         hdcMemMenuLeft, 0, ysrc, SRCCOPY);
  397.                 if(!bTile || w < bmp.bmWidth) break;
  398.             }
  399.             if(!bTile || y == 0) break;
  400.         }
  401.     }
  402. }
  403.  
  404.